package com.zy.cat.common.utils;

import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.taobao.api.internal.util.WebUtils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;

/**
 * 
 * @info 苹果登录API
 * @author Link
 * @date 2020-04-14 16:06
 */
@Slf4j
public class AppleAPI {

	public static final int FAIL_ILLEGAL_REQ = -2;
	public static final int THIRD_AUTH_CODE_INVALID = -1;
	public static final int SUCCESS = 1;

	private String client_id = "com.zhangxing.NineJoyCat"; // 被授权的APP ID
	private String pid = "mm_124488621_35672161_109013650458";
	private String url = "http://mvapi.vephp.com/";

	private AppleAPI(String client_id) {
		super();
		this.client_id = client_id;
	}

	/**
	 * 
	 * @info
	 * @author Link
	 * @date 2020-04-14 18:25
	 * @param type 0.九趣猫账户
	 * @return
	 */
	public static AppleAPI getInstance(int type) {
		String client_id = "com.zhangxing.NineJoyCat"; // 被授权的APP ID
//		if (type == 1) {
//			client_id = "com.example.apple-samplecode.juiceBA4N2246NP"; // 被授权的APPID
//		}
		return new AppleAPI(client_id);
	}

	public static void main(String[] args) {

		String jwt = "eyJraWQiOiJlWGF1bm1MIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLmV4YW1wbGUuYXBwbGUtc2FtcGxlY29kZS5qdWljZUJBNE4yMjQ2TlAiLCJleHAiOjE1ODY4NjAxOTAsImlhdCI6MTU4Njg1OTU5MCwic3ViIjoiMDAxODQwLjExM2VhYWMzM2EzNzRkODdhYmNhNjU4YzBhZDE2MjM2LjA4NDUiLCJjX2hhc2giOiJpeEpJNzBlSmJpX3NvcjRIU0JmRVpnIiwiZW1haWwiOiI3dHo0YWRmbnM2QHByaXZhdGVyZWxheS5hcHBsZWlkLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjoidHJ1ZSIsImlzX3ByaXZhdGVfZW1haWwiOiJ0cnVlIiwiYXV0aF90aW1lIjoxNTg2ODU5NTkwLCJub25jZV9zdXBwb3J0ZWQiOnRydWV9.QIqPQyzfWFYlBEwUXmlOgxrTmwJMN1aLXdzOCu82IIUf56p6_OhvREalTgMA_bJOs3bjbYMFM5_Tys2wYqrn-IA1yPn7sS_uegnT8FD7TYvrG0lllEkA1GkHggFN_JlOFwF4UAXzvZVWtHhVJO6SR3sONI9hgganxC0NU79O09I9TqO8wQFGmJFzB-D2yXuZEl5M-pxbQQ5sYxXVlZEl1p6lIjpqdqh9bkrSfKjfRDGmKtJXO_j9YQYkEGAUnaKZefu09zLRziJOLVY5igGAlUwE1bpKuWFpvVSaiNZhe0f4TTV34Y6UTZ9RH3VGhe59gLKg_AfZ7gah91acBdgPVw";

		String userid = "001840.113eaac33a374d87abca658c0ad16236.0845";

		AppleAPI apple = AppleAPI.getInstance(0);
		Map<String, String> keys = apple.getAppleKeys("");

		log.info("--->" + apple.validateIphone(keys, jwt, userid));
	}

	public Map<String, String> getAppleKeys(String keys) {
		if (StringUtils.isBlank(keys)) {
			try {
				keys = WebUtils.doGet("https://appleid.apple.com/auth/keys", null);
			} catch (IOException e) {
				log.error("获取苹果公钥失败-->" + e.getLocalizedMessage());
				keys = "{\"keys\":[{\"kty\":\"RSA\",\"kid\":\"86D88Kf\",\"use\":\"sig\",\"alg\":\"RS256\",\"n\":\"iGaLqP6y-SJCCBq5Hv6pGDbG_SQ11MNjH7rWHcCFYz4hGwHC4lcSurTlV8u3avoVNM8jXevG1Iu1SY11qInqUvjJur--hghr1b56OPJu6H1iKulSxGjEIyDP6c5BdE1uwprYyr4IO9th8fOwCPygjLFrh44XEGbDIFeImwvBAGOhmMB2AD1n1KviyNsH0bEB7phQtiLk-ILjv1bORSRl8AK677-1T8isGfHKXGZ_ZGtStDe7Lu0Ihp8zoUt59kx2o9uWpROkzF56ypresiIl4WprClRCjz8x6cPZXU2qNWhu71TQvUFwvIvbkE1oYaJMb0jcOTmBRZA2QuYw-zHLwQ\",\"e\":\"AQAB\"},{\"kty\":\"RSA\",\"kid\":\"eXaunmL\",\"use\":\"sig\",\"alg\":\"RS256\",\"n\":\"4dGQ7bQK8LgILOdLsYzfZjkEAoQeVC_aqyc8GC6RX7dq_KvRAQAWPvkam8VQv4GK5T4ogklEKEvj5ISBamdDNq1n52TpxQwI2EqxSk7I9fKPKhRt4F8-2yETlYvye-2s6NeWJim0KBtOVrk0gWvEDgd6WOqJl_yt5WBISvILNyVg1qAAM8JeX6dRPosahRVDjA52G2X-Tip84wqwyRpUlq2ybzcLh3zyhCitBOebiRWDQfG26EH9lTlJhll-p_Dg8vAXxJLIJ4SNLcqgFeZe4OfHLgdzMvxXZJnPp_VgmkcpUdRotazKZumj6dBPcXI_XID4Z4Z3OM1KrZPJNdUhxw\",\"e\":\"AQAB\"}]}";
			}
		}

		JSONObject keysO = JSONObject.parseObject(keys);
		Map<String, String> appleKeys = new HashMap<>();
		if (keysO.containsKey("keys")) {
			keysO.getJSONArray("keys").forEach(action -> {
				JSONObject key = JSONObject.parseObject(action.toString());
				appleKeys.put(key.getString("n"), key.getString("e"));
			});
		}
		log.info("-keys-->" + JSON.toJSONString(appleKeys, true));
		return appleKeys;
	}

	/**
	 * 
	 * @info 首先通过identityToken中的header中的kid，然后结合苹果获取公钥的接口，拿到相应的n和e的值，然后通过下面这个方法构建RSA公钥
	 * @author Link
	 * @date 2020-04-14 16:12
	 * @param n
	 * @param e
	 * @return
	 */
	private RSAPublicKeySpec build(String n, String e) {
		BigInteger modulus = new BigInteger(1, Base64.decodeBase64(n));
		BigInteger publicExponent = new BigInteger(1, Base64.decodeBase64(e));
		return new RSAPublicKeySpec(modulus, publicExponent);
	}

	/**
	 * 
	 * @info 获取验证所需的PublicKey
	 * @author Link
	 * @date 2020-04-14 16:12
	 * @param n
	 * @param e
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 */
	private PublicKey getPublicKey(String n, String e) {
		BigInteger bigIntModulus = new BigInteger(1, Base64.decodeBase64(n));
		BigInteger bigIntPrivateExponent = new BigInteger(1, Base64.decodeBase64(e));
		RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent);
		KeyFactory keyFactory;
		PublicKey publicKey = null;
		try {
			keyFactory = KeyFactory.getInstance("RSA");
			publicKey = keyFactory.generatePublic(keySpec);
		} catch (NoSuchAlgorithmException | InvalidKeySpecException e1) {
			e1.printStackTrace();
		}
		return publicKey;
	}

	/**
	 * 
	 * @info 通过下面这个方法验证JWT的有效性
	 * @author Link
	 * @date 2020-04-14 16:11
	 * @param key      公钥
	 * @param jwt      identityToken：授权用户的JWT凭证
	 * @param audience APPID
	 * @param subject  userId
	 * @return
	 */
	private int verify(PublicKey publicKey, String jwt, String audience, String subject) {
		JwtParser jwtParser = Jwts.parser().setSigningKey(publicKey);
		jwtParser.requireIssuer("https://appleid.apple.com");
		jwtParser.requireAudience(audience);
		jwtParser.requireSubject(subject);
		try {
			Jws<Claims> claim = jwtParser.parseClaimsJws(jwt);
			if (claim != null && claim.getBody().containsKey("auth_time")) {
				log.info("Claims-->" + JSON.toJSONString(claim));
				return SUCCESS;
			}
			return THIRD_AUTH_CODE_INVALID;
		} catch (ExpiredJwtException e) {
			log.error("apple identityToken expired", e);
			return THIRD_AUTH_CODE_INVALID;
		} catch (Exception e) {
			log.error("apple identityToken illegal", e);
			return FAIL_ILLEGAL_REQ;
		}
	}

	/**
	 * 
	 * @info 验证登录信息
	 * @author Link
	 * @date 2020-04-14 18:24
	 * @param keys
	 * @param jwt
	 * @param userid
	 * @return
	 */
	public int validateIphone(Map<String, String> keys, String jwt, String userid) {
		for (String n : keys.keySet()) {
			String e = keys.get(n);
			PublicKey publicKey = getPublicKey(n, e);
			if (verify(publicKey, jwt, this.client_id, userid) == 1) {
				return 1;
			}
		}
		return 0;
	}

}
